mod lib;
use crate::lib::GroupMsg;
extern crate iron;
use iron::prelude::*;
use iron::status;
use std::sync::Mutex;
use std::env;
#[macro_use]
extern crate serde_derive;
extern crate bodyparser;

fn main() {
    let group_msg = Mutex::new(GroupMsg::new());
    let mut arguments = Vec::new();
    for argument in env::args() {
        arguments.push(argument);
    }
    let default = String::from("127.0.0.1:5001");
    if arguments.len() < 2 {
        arguments.insert(1,default);
    }
    println!("host and port {:?}",arguments);
    let req = move |req: &mut Request| -> IronResult<Response> {
        #[warn(unused_assignments)] 
        let mut res = String::from("ok");
        let url: String = req.url.path().get(0).unwrap().to_string();
        // println!("url:{}",url);
        let mut num = group_msg.lock().unwrap();
        //status
        if url == "" {
            res = serde_json::to_string(&num.status()).expect("fail");
        } else
        //debug
        if url == "debug" {
            res = serde_json::to_string(&num.debug()).unwrap();
        } else
        //init
        if url == "init" {
            let struct_body = req.get::<bodyparser::Struct<Ids>>();
            match struct_body {
                Ok(Some(struct_body)) => {
                    &num.init(struct_body.idlist);
                }
                Ok(None) => {
                    println!("No body");
                    res = String::from("fail");
                }
                Err(err) => {
                    println!("Error: {:?}", err);
                    res = String::from("fail");
                }
            }
        } else
        //add_queue
        if url == "add_queue" {
            let struct_body = req.get::<bodyparser::Struct<Id>>();
            match struct_body {
                Ok(Some(struct_body)) => {
                    &num.add_queue(struct_body.id);
                }
                Ok(None) => {
                    println!("No body");
                    res = String::from("fail");
                }
                Err(err) => {
                    println!("Error: {:?}", err);
                    res = String::from("fail");
                }
            }
        } else
        //del_queue
        if url == "del_queue" {
            let struct_body = req.get::<bodyparser::Struct<Id>>();
            match struct_body {
                Ok(Some(struct_body)) => {
                    &num.del_queue(&struct_body.id);
                }
                Ok(None) => {
                    println!("No body");
                    res = String::from("fail");
                }
                Err(err) => {
                    println!("Error: {:?}", err);
                    res = String::from("fail");
                }
            }
        } else
        //send_all_queue
        if url == "send_all_queue" {
            let struct_body = req.get::<bodyparser::Struct<Msg>>();
            match struct_body {
                Ok(Some(struct_body)) => {
                    &num.send_all_queue(struct_body.msg);
                }
                Ok(None) => {
                    println!("No body");
                    res = String::from("fail");
                }
                Err(err) => {
                    println!("Error: {:?}", err);
                    res = String::from("fail");
                }
            }
        } else
        //pull
        if url == "pull" {
            let struct_body = req.get::<bodyparser::Struct<Id>>();
            match struct_body {
                Ok(Some(struct_body)) => {
                    res = num.pull(&struct_body.id);
                }
                Ok(None) => {
                    println!("No body");
                    res = String::from("fail");
                }
                Err(err) => {
                    println!("Error: {:?}", err);
                    res = String::from("fail");
                }
            }
        } else
        //push
        if url == "push" {
            let struct_body = req.get::<bodyparser::Struct<IdMsg>>();
            match struct_body {
                Ok(Some(struct_body)) => {
                    &num.push(&struct_body.id, struct_body.msg);
                }
                Ok(None) => {
                    println!("No body");
                    res = String::from("fail");
                }
                Err(err) => {
                    println!("Error: {:?}", err);
                    res = String::from("fail");
                }
            }
        } else
        //new_group
        if url == "new_group" {
            let struct_body = req.get::<bodyparser::Struct<Group>>();
            match struct_body {
                Ok(Some(struct_body)) => {
                    &num.new_group(struct_body.group);
                }
                Ok(None) => {
                    println!("No body");
                    res = String::from("fail");
                }
                Err(err) => {
                    println!("Error: {:?}", err);
                    res = String::from("fail");
                }
            }
        } else
        //remove_group
        if url == "remove_group" {
            let struct_body = req.get::<bodyparser::Struct<Group>>();
            match struct_body {
                Ok(Some(struct_body)) => {
                    &num.remove_group(&struct_body.group);
                }
                Ok(None) => {
                    println!("No body");
                    res = String::from("fail");
                }
                Err(err) => {
                    println!("Error: {:?}", err);
                    res = String::from("fail");
                }
            }
        } else
        //send_group_message
        if url == "send_group_message" {
            let struct_body = req.get::<bodyparser::Struct<MsgGroup>>();
            match struct_body {
                Ok(Some(struct_body)) => {
                    &num.send_group_message(&struct_body.group, struct_body.msg);
                }
                Ok(None) => {
                    println!("No body");
                    res = String::from("fail");
                }
                Err(err) => {
                    println!("Error: {:?}", err);
                    res = String::from("fail");
                }
            }
        } else
        //add_group_by_id
        if url == "add_group_by_id" {
            let struct_body = req.get::<bodyparser::Struct<GroupId>>();
            match struct_body {
                Ok(Some(struct_body)) => {
                    &num.add_group_by_id(&struct_body.group, &struct_body.id);
                }
                Ok(None) => {
                    println!("No body");
                    res = String::from("fail");
                }
                Err(err) => {
                    println!("Error: {:?}", err);
                    res = String::from("fail");
                }
            }
        } else
        //del_group_by_id
        if url == "del_group_by_id" {
            let struct_body = req.get::<bodyparser::Struct<GroupId>>();
            match struct_body {
                Ok(Some(struct_body)) => {
                    &num.del_group_by_id(&struct_body.group, &struct_body.id);
                }
                Ok(None) => {
                    println!("No body");
                    res = String::from("fail");
                }
                Err(err) => {
                    println!("Error: {:?}", err);
                    res = String::from("fail");
                }
            }
        } else {
            res = String::from("null");
        }

        Ok(Response::with((status::Ok, res)))
    };

    let _server = Iron::new(req).http(&arguments[1]).unwrap();
}

#[derive(Clone, Serialize, Deserialize)]
struct Ids {
    idlist: Vec<i64>,
}

#[derive(Clone, Serialize, Deserialize)]
struct Id {
    id: i64,
}
#[derive(Clone, Serialize, Deserialize)]
struct Msg {
    msg: String,
}

#[derive(Clone, Serialize, Deserialize)]
struct IdMsg {
    id: i64,
    msg: String,
}

#[derive(Clone, Serialize, Deserialize)]
struct Group {
    group: String,
}

#[derive(Clone, Serialize, Deserialize)]
struct MsgGroup {
    group: String,
    msg: String,
}

#[derive(Clone, Serialize, Deserialize)]
struct GroupId {
    group: String,
    id: i64,
}
